import socket
import uuid
from prg.proc.server_run import RunServer
from prg.bll.config_bll import ConfigBll
from prg.proc.handle_thread import HandleThread
from prg.proc.keep_thread import KeepAlive
from prg.proc.command_thread import RunCommand
from prg.bll.authority_bll import AuthorityBll
from prg.server_command import ServerCommand
from prg.entity.arg_entity import ArgBase
from prg.entity.public_entity import PublicEntity
from prg.proc.server_link import ServerLink


class LinkSvr:

    def __init__(self):
        self.config = ConfigBll.instance()
        self.user = AuthorityBll.instance()
        self.run = True
        self.command = RunCommand()
        self.handel = HandleThread()
        self.keep_alive = KeepAlive()
        self.svr_id = 0
        self.svr_link = ServerLink()
        self.svr_link.server_start()
        self.connect_parent()

    def connect_parent(self):
        parent_addr = ConfigBll.instance().get_server().parent
        address = parent_addr.split("/", 1)
        svr_cmd = ServerCommand()
        svr_cmd.connect(parent_address=(address[0], int(address[1])))
        arg = ArgBase()
        arg.sign = str(uuid.uuid1())
        svr_cmd.send(command="bind", arg=arg, callback=self.svr_callback)

    def svr_callback(self, header_en):
        if "bind" == header_en.command:
            self.svr_id = header_en.arg.arg_dict["id"]
            PublicEntity.instance().server_id = self.svr_id
            print("server id: %s" % self.svr_id)

    def open_listen(self):
        ip = self.config.get_ip()
        port = self.config.get_port()
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.bind((ip, port))
        server_socket.listen(10)

        self.handel.start()
        self.keep_alive.start()
        self.command.start()

        while self.run:
            client_socket, client_address = server_socket.accept()
            print("[%s, %s]user connected" % client_address)
            server = RunServer(socket_item=client_socket)
            server.start()
